#include <windows.h>
#include<iostream>
#include <conio.h>
#include <random>
#include "snake.h"
#include <io.h>      // 用于 _setmode
#include <fcntl.h>   // 用于 _O_U16TEXT
int speed = 200;
Position oldTail;
using namespace std;
void drawGameOver();
void gotoXY(int x, int y);
void resetSnake()
{
    Snake temp;
    s1 = temp;
    score =0 ;
}
void hideCursor() {
    HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO info;
    info.dwSize = 100;
    info.bVisible = FALSE;
    SetConsoleCursorInfo(consoleHandle, &info);
}
void updatesnake() {
    // 保存旧的头部位置
    Position oldHead = s1.head;

    // 移动头部
    s1.head.x += kx;
    s1.head.y += ky;
    // 移动身体 - 每个身体部分移动到前一个部分的位置
    if (!s1.body.empty()) {
        // 保存旧的尾部位置
        oldTail = s1.body.back();
        oldTail.flag = 1;
        // 从后向前更新身体位置
        for (int i = s1.body.size() - 1; i > 0; i--) {
            s1.body[i] = s1.body[i - 1];
        }

        // 第一个身体部分移动到旧头部位置
        s1.body[0] = oldHead;
    }
}
//蛇的显示
void snakeUI()
{
    gotoXY(s1.head.x, s1.head.y);
    putchar('@');
    for (int i = 0; i < s1.size - 1; i++)
    {
        gotoXY(s1.body[i].x, s1.body[i].y);
        putchar('*');
    }
   
    //检查原尾部是否有食物
    for (int i = 0; i < f.size(); i++)
    {
        if (oldTail.x == f[i].x && oldTail.y == f[i].y)return;
    }

    if (oldTail.flag)
    {
        gotoXY(oldTail.x, oldTail.y);
        putchar(' ');
    }
}
//显示食物
void spawnFood()
{
    
    for (int i = 0; i < f.size(); i++)
    {
        gotoXY(f[i].x, f[i].y);      
        putchar('#');
    }
}
void initUI()
{
    gotoXY(s1.head.x, s1.head.y);
    putchar( '@');
    for (int i = 0; i < s1.size - 1; i++)
    {
        gotoXY(s1.body[i].x, s1.body[i].y);
        putchar('*');
    }    
}
void foodEat()
{
    for (int i = 0; i < f.size(); i++)
    {
        if (s1.head.x == f[i].x && s1.head.y == f[i].y) {
            score+=4;
            s1.size++;//蛇长度增长
            s1.body.push_back(oldTail);
            oldTail.flag=0;
           
            f.erase(f.begin() + i);
            f.emplace(f.begin() + i, rand() % 60+1, rand() % 20+1);
            gotoXY(f[i].x, f[i].y);
            putchar('#');
        }
    }
}

void playGame()
{
    bool isRuning = true;
    bool hasStart = false;
    char key;
   
    while (isRuning)
    {


        if (_kbhit())
        {
            //初始移动方向
            char key = _getch();
            while (isRuning)
            {
                //更改方向
                if (_kbhit())key = _getch();
                switch (tolower(key))
                {
                case 'w':
                    if (ky != 1)
                    { // 防止直接反向
                        kx = 0;
                        ky = -1;

                    }
                    break;
                case 's':
                    if (ky != -1)
                    {
                        kx = 0;
                        ky = 1;

                    }
                    break;
                case 'a':
                    if (kx != 1)
                    {
                        kx = -1;
                        ky = 0;

                    }
                    break;
                case 'd':
                    if (kx != -1)
                    {
                        kx = 1;
                        ky = 0;

                    }
                    break;
                }

                updatesnake();
                foodEat();
                snakeUI();
                if (s1.head.x <= 0 || s1.head.x >= WIDTH+1 || s1.head.y <= 0 || s1.head.y >= HIGHT+1)drawGameOver();
                for (int i = 0; i < s1.size - 1; i++)
                {
                    if (s1.head.x == s1.body[i].x && s1.head.y == s1.body[i].y)

                        drawGameOver();//游戏结束
                }
                //蛇是否吃食物
                
                //更新蛇位置

               
                Sleep(speed);
            }
        }

    }
    
}
// 设置光标位置
void gotoXY(int x, int y) {
    COORD coord = { static_cast<SHORT>(x), static_cast<SHORT>(y) };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void drawMainMenu(int selectedOption) {
    system("cls");

    // 游戏标题
    gotoXY(30, 5);
    cout << "=== 贪吃蛇游戏 ===";

    // 菜单选项
    gotoXY(32, 10);
    cout << (selectedOption == 0 ? "> " : "  ") << "1. 开始游戏";

    gotoXY(32, 12);
    cout << (selectedOption == 1 ? "> " : "  ") << "2. 游戏说明";

    gotoXY(32, 14);
    cout << (selectedOption == 2 ? "> " : "  ") << "3. 退出游戏";

    // 操作提示
    gotoXY(25, 20);
    cout << "使用 W/S 键选择，Enter 键确认，Esc键退出程序";
    
}
void drawInstructions() {
    system("cls");

    gotoXY(25, 3);
    cout << "=== 游戏说明 ===";

    gotoXY(20, 6);
    cout << "控制方式:";
    gotoXY(22, 8);
    cout << "W - 向上移动";
    gotoXY(22, 9);
    cout << "S - 向下移动";
    gotoXY(22, 10);
    cout << "A - 向左移动";
    gotoXY(22, 11);
    cout << "D - 向右移动";

    gotoXY(20, 14);
    cout << "游戏规则:";
    gotoXY(22, 16);
    cout << "1. 控制蛇吃食物(@)增加长度";
    gotoXY(22, 17);
    cout << "2. 撞到墙壁或自己身体游戏结束";

    gotoXY(25, 20);
    cout << "按任意键返回主菜单...";
}
void drawBorder() {
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

    // 使用Box-drawing字符
    const wchar_t border[] = {
        L'╔', L'═', L'╗',  // 上边框
        L'║', L' ', L'║',  // 左右边框
        L'╚', L'═', L'╝'   // 下边框
    };

    // 设置控制台输出为UTF-8
    SetConsoleOutputCP(65001);
    SetConsoleCP(65001);
    _setmode(_fileno(stdout), _O_U16TEXT);//设置为宽字符输出模式
    // 绘制上边框
    
    gotoXY(0, 0);
    wcout << border[0];
    for (int i = 0; i < WIDTH; i++) wcout << border[1];
    wcout << border[2];

    // 绘制左右边框
    for (int y = 1; y <= HIGHT+1; y++) {
        gotoXY(0, y);
        wcout << border[3];

        gotoXY(WIDTH + 1, y);
        wcout << border[5];
    }

    // 绘制下边框
    gotoXY(0, HIGHT + 1);
    wcout << border[6];
    for (int i = 0; i < WIDTH; i++) wcout << border[7];
    wcout << border[8];
    _setmode(_fileno(stdout), _O_TEXT);
    SetConsoleOutputCP(GetACP());  // 恢复为系统默认代码页
}
void handleMainMenu() {
    hideCursor();
    int selectedOption = 0; // 0:开始游戏, 1:游戏说明, 2:退出游戏

    while (true) {
        drawMainMenu(selectedOption);

        int key = _getch();

        // 处理方向键和确认键
        switch (tolower(key)) {
        case 'w':
       
            selectedOption = (selectedOption - 1 + 3) % 3; // 循环选择
            break;

        case 's':
        
            selectedOption = (selectedOption + 1) % 3; // 循环选择
            break;

        case 13: // Enter键
            switch (selectedOption) {
            case 0:
                system("cls");
                drawBorder();
                initUI();//将蛇显示于画面中
                spawnFood(); 
                playGame(); return;
            case 1:
                drawInstructions();
                _getch(); // 等待任意键
                break;
            case 2: exit(0);
            }
            break;

        case 27: // ESC键
            exit(0);
        }
    }
}
void drawGameOver() {
    system("cls");

    // 计算居中位置
    int centerX = WIDTH / 2 - 4;
    int centerY = HIGHT / 2;

    // 绘制Game Over文字
    gotoXY(centerX, centerY);
    cout << "==============";
    gotoXY(centerX, centerY + 1);
    cout << "| GAME OVER! |";
    gotoXY(centerX, centerY + 2);
    cout << "==============";

    // 显示得分
    gotoXY(centerX, centerY + 4);
    cout << "得分: " << score;

    // 操作提示
    gotoXY(centerX - 5, centerY + 6);

    cout << "按R重新开始，按Q退出";
    while (1) {
        resetSnake();
        char key1 = _getch();
        switch (tolower(key1))
        {
        case 'r':
            system("cls");
            drawBorder();
            
            initUI();//将蛇显示于画面中
            spawnFood();
            playGame(); break;
        case'q':
          
            handleMainMenu();
            break;
        }
    }
}
int main()
{
    hideCursor();
    //设置随机数种子
    srand(time(nullptr));
    handleMainMenu();
    return 0;
}